'use strict'

const chai = require('chai')
const runServerless = require('../../../../../../../../../utils/run-serverless')

const { expect } = chai

const healthCheckDefaults = {
  HealthCheckEnabled: false,
  HealthCheckPath: '/',
  HealthCheckIntervalSeconds: 35,
  HealthCheckTimeoutSeconds: 30,
  HealthyThresholdCount: 5,
  UnhealthyThresholdCount: 5,
  Matcher: { HttpCode: '200' },
}

const serverlessConfigurationExtension = {
  functions: {
    default: {
      handler: 'index.handler',
      events: [
        {
          alb: {
            listenerArn:
              'arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/my-load-balancer/50dc6c495c0c9188/f2f7dc8efc522ab2',
            conditions: {
              path: '/',
            },
            priority: 1,
          },
        },
      ],
    },
    enabledTrue: {
      handler: 'index.handler',
      events: [
        {
          alb: {
            listenerArn:
              'arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/my-load-balancer/50dc6c495c0c9188/f2f7dc8efc522ab2',
            conditions: {
              path: '/',
            },
            priority: 2,
            healthCheck: true,
          },
        },
      ],
    },
    enabledFalse: {
      handler: 'index.handler',
      events: [
        {
          alb: {
            listenerArn:
              'arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/my-load-balancer/50dc6c495c0c9188/f2f7dc8efc522ab2',
            conditions: {
              path: '/',
            },
            priority: 3,
            healthCheck: false,
          },
        },
      ],
    },
    enabledAdvanced: {
      handler: 'index.handler',
      events: [
        {
          alb: {
            listenerArn:
              'arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/my-load-balancer/50dc6c495c0c9188/f2f7dc8efc522ab2',
            conditions: {
              path: '/',
            },
            priority: 4,
            healthCheck: {
              path: '/health',
              intervalSeconds: 70,
              timeoutSeconds: 50,
              healthyThresholdCount: 7,
              unhealthyThresholdCount: 7,
              matcher: {
                httpCode: '200-299',
              },
            },
          },
        },
      ],
    },
    enabledAdvancedPartial: {
      handler: 'index.handler',
      events: [
        {
          alb: {
            listenerArn:
              'arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/my-load-balancer/50dc6c495c0c9188/f2f7dc8efc522ab2',
            conditions: {
              path: '/',
            },
            priority: 5,
            healthCheck: {
              path: '/health',
              intervalSeconds: 70,
            },
          },
        },
      ],
    },
  },
}

describe('ALB TargetGroup Health Checks', () => {
  let cfResources
  let naming

  before(async () =>
    runServerless({
      fixture: 'function',
      configExt: serverlessConfigurationExtension,
      command: 'package',
    }).then(({ cfTemplate, awsNaming }) => {
      ;({ Resources: cfResources } = cfTemplate)
      naming = awsNaming
    }),
  )

  it('should be forcibly reverted to its default state (disabled) if healthCheck is not set', () => {
    const albTargetGroupName = naming.getAlbTargetGroupLogicalId(
      'default',
      '50dc6c495c0c9188',
    )

    const targetGroup = cfResources[albTargetGroupName]
    expect(targetGroup.Type).to.equal(
      'AWS::ElasticLoadBalancingV2::TargetGroup',
    )

    const properties = targetGroup.Properties
    expect(properties.HealthCheckEnabled).to.equal(
      healthCheckDefaults.HealthCheckEnabled,
    )
    expect(properties.HealthCheckPath).to.be.undefined
    expect(properties.HealthCheckIntervalSeconds).to.be.undefined
    expect(properties.HealthCheckTimeoutSeconds).to.be.undefined
    expect(properties.HealthyThresholdCount).to.be.undefined
    expect(properties.UnhealthyThresholdCount).to.be.undefined
    expect(properties.Matcher).to.be.undefined
  })

  it('should be disabled when healthCheck is explicitly false', () => {
    const albTargetGroupName = naming.getAlbTargetGroupLogicalId(
      'enabledFalse',
      '50dc6c495c0c9188',
    )

    const targetGroup = cfResources[albTargetGroupName]
    expect(targetGroup.Type).to.equal(
      'AWS::ElasticLoadBalancingV2::TargetGroup',
    )

    const properties = targetGroup.Properties
    expect(properties.HealthCheckEnabled).to.be.false
  })

  it('should be enabled with default settings when healthCheck is explicitly true', () => {
    const albTargetGroupName = naming.getAlbTargetGroupLogicalId(
      'enabledTrue',
      '50dc6c495c0c9188',
    )

    const targetGroup = cfResources[albTargetGroupName]
    expect(targetGroup.Type).to.equal(
      'AWS::ElasticLoadBalancingV2::TargetGroup',
    )

    const properties = targetGroup.Properties
    expect(properties.HealthCheckEnabled).to.be.true
    expect(properties.HealthCheckPath).to.equal(
      healthCheckDefaults.HealthCheckPath,
    )
    expect(properties.HealthCheckIntervalSeconds).to.equal(
      healthCheckDefaults.HealthCheckIntervalSeconds,
    )
    expect(properties.HealthCheckTimeoutSeconds).to.equal(
      healthCheckDefaults.HealthCheckTimeoutSeconds,
    )
    expect(properties.HealthyThresholdCount).to.equal(
      healthCheckDefaults.HealthyThresholdCount,
    )
    expect(properties.UnhealthyThresholdCount).to.equal(
      healthCheckDefaults.UnhealthyThresholdCount,
    )
    expect(properties.Matcher).to.deep.equal(healthCheckDefaults.Matcher)
  })

  it('should be enabled with custom settings when healthCheck value is an object', () => {
    const albTargetGroupName = naming.getAlbTargetGroupLogicalId(
      'enabledAdvanced',
      '50dc6c495c0c9188',
    )

    const targetGroup = cfResources[albTargetGroupName]
    expect(targetGroup.Type).to.equal(
      'AWS::ElasticLoadBalancingV2::TargetGroup',
    )

    const properties = targetGroup.Properties
    expect(properties.HealthCheckEnabled).to.be.true
    expect(properties.HealthCheckPath).to.equal('/health')
    expect(properties.HealthCheckIntervalSeconds).to.equal(70)
    expect(properties.HealthCheckTimeoutSeconds).to.equal(50)
    expect(properties.HealthyThresholdCount).to.equal(7)
    expect(properties.UnhealthyThresholdCount).to.equal(7)
    expect(properties.Matcher.HttpCode).to.equal('200-299')
  })

  it('should use defaults for any undefined advanced settings', () => {
    const albTargetGroupName = naming.getAlbTargetGroupLogicalId(
      'enabledAdvancedPartial',
      '50dc6c495c0c9188',
    )

    const targetGroup = cfResources[albTargetGroupName]
    expect(targetGroup.Type).to.equal(
      'AWS::ElasticLoadBalancingV2::TargetGroup',
    )

    const properties = targetGroup.Properties
    expect(properties.HealthCheckEnabled).to.be.true
    expect(properties.HealthCheckPath).to.equal('/health')
    expect(properties.HealthCheckIntervalSeconds).to.equal(70)
    expect(properties.HealthCheckTimeoutSeconds).to.equal(
      healthCheckDefaults.HealthCheckTimeoutSeconds,
    )
    expect(properties.HealthyThresholdCount).to.equal(
      healthCheckDefaults.HealthyThresholdCount,
    )
    expect(properties.UnhealthyThresholdCount).to.equal(
      healthCheckDefaults.UnhealthyThresholdCount,
    )
    expect(properties.Matcher).to.deep.equal(healthCheckDefaults.Matcher)
  })
})
